//Copyright 2010 Balazs Keri, Imre Keri
//
//This file is part of FireworksCreator.
//
//FireworksCreator is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//FireworksCreator is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with FireworksCreator.  If not, see <http://www.gnu.org/licenses/>.
//
#include "emitterevaluator.h"
#include "emitter.h"
#include "particle.h"
#include "particleparam.h"
#include "controller.h"
//
namespace player
{
EmitterEvaluator::EmitterEvaluator()
:
   emitter(0),
   t_start(-1),
   t_end(-1),
   dt_min(0),
   dt_max(0),
   current_t_trigger(0)
{
}
EmitterEvaluator::EmitterEvaluator(const Emitter *p_emitter,double p_t_start)
:
   emitter(p_emitter),
   t_start(p_t_start),
   t_end(p_t_start),
   dt_min(0),
   dt_max(0),
   current_t_trigger(-1)
{
}
EmitterEvaluator::EmitterEvaluator(const Emitter *p_emitter,double p_t_start,double p_t_end,double p_dt_min,double p_dt_max)
:
   emitter(p_emitter),
   t_start(p_t_start),
   t_end(p_t_end),
   dt_min(p_dt_min),
   dt_max(p_dt_max),
   current_t_trigger(0)
{
}
EmitterEvaluator::EmitterEvaluator(const EmitterEvaluator &p_other)
:
   emitter(p_other.emitter),
   t_start(p_other.t_start),
   t_end(p_other.t_end),
   dt_min(p_other.dt_min),
   dt_max(p_other.dt_max),
   current_t_trigger(p_other.current_t_trigger)
{
}
EmitterEvaluator &EmitterEvaluator::operator=(const EmitterEvaluator &p_other)
{
   if(&p_other!=this)
   {
      emitter=p_other.emitter;
      t_start=p_other.t_start;
      t_end=p_other.t_end;
      dt_min=p_other.dt_min;
      dt_max=p_other.dt_max;
      current_t_trigger=p_other.current_t_trigger;
   }
   return *this;
}
//
void EmitterEvaluator::start()
{
   if(t_start==t_end)
   {
      current_t_trigger=t_start;
      //negative start time results in no triggering at all
   }
   else
   {
      if(t_start>=0)
         current_t_trigger=t_start;
      else
      {
         //not accurate but OK, this is anyway an "invalid case"
         current_t_trigger=(static_cast<double>(qrand())/(RAND_MAX-1))*dt_max;
         if(current_t_trigger>t_end)
            current_t_trigger=-1;
      }
   }
}
void EmitterEvaluator::update(const Particle *p_particle)
{
   //check if already triggered (or not at all)
   if(current_t_trigger<0)
      return;
   //
   //if to trigger
   if(p_particle->get_age()>=current_t_trigger)
   {
      ParticleParam p;
      //trigger it now, not when it "should have been"
      //this is not accurate but should work OK if dt is small enough
      p.time=emitter->get_controller()->get_current_time();
      p.position=p_particle->get_position();
      p.velocity=p_particle->get_velocity();
      p.angle=p_particle->get_angle();
      p.angular_velocity=p_particle->get_angular_velocity();
      emitter->trigger(p);
      if(t_start==t_end)
         current_t_trigger=-1;
      else
      {
         while(current_t_trigger<=p_particle->get_age())
            current_t_trigger+=get_dt();
         if(current_t_trigger>t_end)
            current_t_trigger = -1;
      }
   }
}
double EmitterEvaluator::get_dt()const
{
   return dt_min+(static_cast<double>(qrand())/(RAND_MAX-1))*(dt_max-dt_min);
}
}
